// Copyright 2009 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: Jeff Stewart
//
// Executive is the glue of this project.  It creates the probes and manages
// their execution.  It emits appropriate signals to allow UI display of
// progress.  Create an Executive, then call Start().
// ProgressMade() will be emitted as progress is made.  Call GetProgress to
// get the data you need to update progress bars in response to this.
// ProbeCompleted and ProbeStarted will let you monitor the fine grain progress
// of the executive, if your UI demands it.
// ReportReady will tell you that the report you requested is ready.

#ifndef POPDIAG_PROBES_EXECUTIVE_H__
#define POPDIAG_PROBES_EXECUTIVE_H__


#include "probes/probe.h"
#include "util/common.h"

namespace popdiag {

class SmtpProbe;
class ReportGenerator;

struct ExecutiveOptions {
  QString username;     // The username to authenticate our probes with.
  QString password;
  QString imap_server;  // The DNS name of the imap server.  IP addresses won't
                        // work because we're going to do a SSL cert check
                        // against this name.
  QString pop_server;   // The DNS name of the pop server.  IP addresses will
                        // not work.  See above.
  QString smtp_server;  // The DNS name of the smtp server.  IP address will
                        // not work.  See above.
  int smtp_port;        // The SMTP port to probe.  Should be 465 or 587.
                        // TLS or SSL is derived from this value.
  QString config_log;   // A record of the configuration check.
  bool pull_all_mail;   // If true, pull all mail via POP.  Otherwise pull
                        // a single message.
};

class Executive : public QObject {
  Q_OBJECT
 public:
  // Create an executive owned by parent with the given options.
  Executive(QObject *parent, const ExecutiveOptions &options);
  virtual ~Executive();

  // Request that the executive stop running after the current probe finishes.
  // Does not block.
  void Abort();

  // Get the probes contained in this Executive.  Caller does not own the
  // pointer returned and it's only valid as long as the executive remains
  // valid.
  ProbeSet *probes();

  // Get an English HTML report of the proceedings of this Executive.
  inline const QString &GetReport() { return report_; }

  // Start up the executive.  This call must not block.
  void Start();

  // Get the progress of the tests.
  void GetProgress(int *completed, int *estimated_total);

  private slots:
  void UpdateProgress();

 signals:
  // Get the text/html payload with the GetReport() method after this
  // signal has been emitted.
  void ReportReady();

  void ProbeStarted(Probe *p);

  void ProbeCompleted(Probe *p);

  void ProgressMade(int completed, int estimated_total);

  // Emitted when we're done running probes.
  void Done();

  private slots:
  void ProbeDone();

 private:
  void QueueNextProbe();
  void ProbesDone();

  ReportGenerator *reporter_;     // Generates our reports.
  Probe *current_probe_;          // The running probe.  Owned by probes_.
  ExecutiveOptions options_;      // Construction options.  See constructor
                                  // comments for details.
  QString report_;                // Our report of the probe results.
  scoped_ptr<ProbeSet> probes_;   // The set of probes we will run.  Owns the
                                  // probe pointers.
  bool abort_;                    // If true, don't start any more probes.
  int progress_completed_;        // Progress completed so far.
  int progress_estimated_total_;  // Estimated total progress to be made.

  DISALLOW_EVIL_CONSTRUCTORS(Executive);
};

}  // namespace popdiag

#endif  // POPDIAG_PROBES_EXECUTIVE_H__
